/* eslint-disable @typescript-eslint/no-magic-numbers */
import type { Contribution4D } from "../Contributions.js";
import { shuffleSeed } from "../utils.js";

export class SimplexNoise4D {
    private readonly _NORM_4D;
    private readonly _SQUISH_4D;
    private readonly _STRETCH_4D;

    private readonly _base4D;
    private readonly _gradients4D;
    private _lookup: Contribution4D[];
    private readonly _lookupPairs4D;
    private readonly _p4D;
    private _perm: Uint8Array;
    private _perm4D: Uint8Array;

    constructor() {
        this._NORM_4D = 1.0 / 30.0;
        this._SQUISH_4D = (Math.sqrt(4 + 1) - 1) * 0.25;
        this._STRETCH_4D = (1 / Math.sqrt(4 + 1) - 1) * 0.25;
        this._lookup = [];
        this._perm = new Uint8Array(0);
        this._perm4D = new Uint8Array(0);

        this._base4D = [
            [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1],
            [3, 1, 1, 1, 0, 3, 1, 1, 0, 1, 3, 1, 0, 1, 1, 3, 0, 1, 1, 1, 4, 1, 1, 1, 1],
            [
                1,
                1,
                0,
                0,
                0,
                1,
                0,
                1,
                0,
                0,
                1,
                0,
                0,
                1,
                0,
                1,
                0,
                0,
                0,
                1,
                2,
                1,
                1,
                0,
                0,
                2,
                1,
                0,
                1,
                0,
                2,
                1,
                0,
                0,
                1,
                2,
                0,
                1,
                1,
                0,
                2,
                0,
                1,
                0,
                1,
                2,
                0,
                0,
                1,
                1,
            ],
            [
                3,
                1,
                1,
                1,
                0,
                3,
                1,
                1,
                0,
                1,
                3,
                1,
                0,
                1,
                1,
                3,
                0,
                1,
                1,
                1,
                2,
                1,
                1,
                0,
                0,
                2,
                1,
                0,
                1,
                0,
                2,
                1,
                0,
                0,
                1,
                2,
                0,
                1,
                1,
                0,
                2,
                0,
                1,
                0,
                1,
                2,
                0,
                0,
                1,
                1,
            ],
        ];
        this._gradients4D = [
            3,
            1,
            1,
            1,
            1,
            3,
            1,
            1,
            1,
            1,
            3,
            1,
            1,
            1,
            1,
            3,
            -3,
            1,
            1,
            1,
            -1,
            3,
            1,
            1,
            -1,
            1,
            3,
            1,
            -1,
            1,
            1,
            3,
            3,
            -1,
            1,
            1,
            1,
            -3,
            1,
            1,
            1,
            -1,
            3,
            1,
            1,
            -1,
            1,
            3,
            -3,
            -1,
            1,
            1,
            -1,
            -3,
            1,
            1,
            -1,
            -1,
            3,
            1,
            -1,
            -1,
            1,
            3,
            3,
            1,
            -1,
            1,
            1,
            3,
            -1,
            1,
            1,
            1,
            -3,
            1,
            1,
            1,
            -1,
            3,
            -3,
            1,
            -1,
            1,
            -1,
            3,
            -1,
            1,
            -1,
            1,
            -3,
            1,
            -1,
            1,
            -1,
            3,
            3,
            -1,
            -1,
            1,
            1,
            -3,
            -1,
            1,
            1,
            -1,
            -3,
            1,
            1,
            -1,
            -1,
            3,
            -3,
            -1,
            -1,
            1,
            -1,
            -3,
            -1,
            1,
            -1,
            -1,
            -3,
            1,
            -1,
            -1,
            -1,
            3,
            3,
            1,
            1,
            -1,
            1,
            3,
            1,
            -1,
            1,
            1,
            3,
            -1,
            1,
            1,
            1,
            -3,
            -3,
            1,
            1,
            -1,
            -1,
            3,
            1,
            -1,
            -1,
            1,
            3,
            -1,
            -1,
            1,
            1,
            -3,
            3,
            -1,
            1,
            -1,
            1,
            -3,
            1,
            -1,
            1,
            -1,
            3,
            -1,
            1,
            -1,
            1,
            -3,
            -3,
            -1,
            1,
            -1,
            -1,
            -3,
            1,
            -1,
            -1,
            -1,
            3,
            -1,
            -1,
            -1,
            1,
            -3,
            3,
            1,
            -1,
            -1,
            1,
            3,
            -1,
            -1,
            1,
            1,
            -3,
            -1,
            1,
            1,
            -1,
            -3,
            -3,
            1,
            -1,
            -1,
            -1,
            3,
            -1,
            -1,
            -1,
            1,
            -3,
            -1,
            -1,
            1,
            -1,
            -3,
            3,
            -1,
            -1,
            -1,
            1,
            -3,
            -1,
            -1,
            1,
            -1,
            -3,
            -1,
            1,
            -1,
            -1,
            -3,
            -3,
            -1,
            -1,
            -1,
            -1,
            -3,
            -1,
            -1,
            -1,
            -1,
            -3,
            -1,
            -1,
            -1,
            -1,
            -3,
        ];
        this._lookupPairs4D = [
            0,
            3,
            1,
            2,
            2,
            3,
            5,
            2,
            6,
            1,
            7,
            1,
            8,
            3,
            9,
            2,
            10,
            3,
            13,
            2,
            16,
            3,
            18,
            3,
            22,
            1,
            23,
            1,
            24,
            3,
            26,
            3,
            33,
            2,
            37,
            2,
            38,
            1,
            39,
            1,
            41,
            2,
            45,
            2,
            54,
            1,
            55,
            1,
            56,
            0,
            57,
            0,
            58,
            0,
            59,
            0,
            60,
            0,
            61,
            0,
            62,
            0,
            63,
            0,
            256,
            3,
            258,
            3,
            264,
            3,
            266,
            3,
            272,
            3,
            274,
            3,
            280,
            3,
            282,
            3,
            2049,
            2,
            2053,
            2,
            2057,
            2,
            2061,
            2,
            2081,
            2,
            2085,
            2,
            2089,
            2,
            2093,
            2,
            2304,
            9,
            2305,
            9,
            2312,
            9,
            2313,
            9,
            16390,
            1,
            16391,
            1,
            16406,
            1,
            16407,
            1,
            16422,
            1,
            16423,
            1,
            16438,
            1,
            16439,
            1,
            16642,
            8,
            16646,
            8,
            16658,
            8,
            16662,
            8,
            18437,
            6,
            18439,
            6,
            18469,
            6,
            18471,
            6,
            18688,
            9,
            18689,
            9,
            18690,
            8,
            18693,
            6,
            18694,
            8,
            18695,
            6,
            18696,
            9,
            18697,
            9,
            18706,
            8,
            18710,
            8,
            18725,
            6,
            18727,
            6,
            131128,
            0,
            131129,
            0,
            131130,
            0,
            131131,
            0,
            131132,
            0,
            131133,
            0,
            131134,
            0,
            131135,
            0,
            131352,
            7,
            131354,
            7,
            131384,
            7,
            131386,
            7,
            133161,
            5,
            133165,
            5,
            133177,
            5,
            133181,
            5,
            133376,
            9,
            133377,
            9,
            133384,
            9,
            133385,
            9,
            133400,
            7,
            133402,
            7,
            133417,
            5,
            133421,
            5,
            133432,
            7,
            133433,
            5,
            133434,
            7,
            133437,
            5,
            147510,
            4,
            147511,
            4,
            147518,
            4,
            147519,
            4,
            147714,
            8,
            147718,
            8,
            147730,
            8,
            147734,
            8,
            147736,
            7,
            147738,
            7,
            147766,
            4,
            147767,
            4,
            147768,
            7,
            147770,
            7,
            147774,
            4,
            147775,
            4,
            149509,
            6,
            149511,
            6,
            149541,
            6,
            149543,
            6,
            149545,
            5,
            149549,
            5,
            149558,
            4,
            149559,
            4,
            149561,
            5,
            149565,
            5,
            149566,
            4,
            149567,
            4,
            149760,
            9,
            149761,
            9,
            149762,
            8,
            149765,
            6,
            149766,
            8,
            149767,
            6,
            149768,
            9,
            149769,
            9,
            149778,
            8,
            149782,
            8,
            149784,
            7,
            149786,
            7,
            149797,
            6,
            149799,
            6,
            149801,
            5,
            149805,
            5,
            149814,
            4,
            149815,
            4,
            149816,
            7,
            149817,
            5,
            149818,
            7,
            149821,
            5,
            149822,
            4,
            149823,
            4,
            149824,
            37,
            149825,
            37,
            149826,
            36,
            149829,
            34,
            149830,
            36,
            149831,
            34,
            149832,
            37,
            149833,
            37,
            149842,
            36,
            149846,
            36,
            149848,
            35,
            149850,
            35,
            149861,
            34,
            149863,
            34,
            149865,
            33,
            149869,
            33,
            149878,
            32,
            149879,
            32,
            149880,
            35,
            149881,
            33,
            149882,
            35,
            149885,
            33,
            149886,
            32,
            149887,
            32,
            150080,
            49,
            150082,
            48,
            150088,
            49,
            150098,
            48,
            150104,
            47,
            150106,
            47,
            151873,
            46,
            151877,
            45,
            151881,
            46,
            151909,
            45,
            151913,
            44,
            151917,
            44,
            152128,
            49,
            152129,
            46,
            152136,
            49,
            152137,
            46,
            166214,
            43,
            166215,
            42,
            166230,
            43,
            166247,
            42,
            166262,
            41,
            166263,
            41,
            166466,
            48,
            166470,
            43,
            166482,
            48,
            166486,
            43,
            168261,
            45,
            168263,
            42,
            168293,
            45,
            168295,
            42,
            168512,
            31,
            168513,
            28,
            168514,
            31,
            168517,
            28,
            168518,
            25,
            168519,
            25,
            280952,
            40,
            280953,
            39,
            280954,
            40,
            280957,
            39,
            280958,
            38,
            280959,
            38,
            281176,
            47,
            281178,
            47,
            281208,
            40,
            281210,
            40,
            282985,
            44,
            282989,
            44,
            283001,
            39,
            283005,
            39,
            283208,
            30,
            283209,
            27,
            283224,
            30,
            283241,
            27,
            283256,
            22,
            283257,
            22,
            297334,
            41,
            297335,
            41,
            297342,
            38,
            297343,
            38,
            297554,
            29,
            297558,
            24,
            297562,
            29,
            297590,
            24,
            297594,
            21,
            297598,
            21,
            299365,
            26,
            299367,
            23,
            299373,
            26,
            299383,
            23,
            299389,
            20,
            299391,
            20,
            299584,
            31,
            299585,
            28,
            299586,
            31,
            299589,
            28,
            299590,
            25,
            299591,
            25,
            299592,
            30,
            299593,
            27,
            299602,
            29,
            299606,
            24,
            299608,
            30,
            299610,
            29,
            299621,
            26,
            299623,
            23,
            299625,
            27,
            299629,
            26,
            299638,
            24,
            299639,
            23,
            299640,
            22,
            299641,
            22,
            299642,
            21,
            299645,
            20,
            299646,
            21,
            299647,
            20,
            299648,
            61,
            299649,
            60,
            299650,
            61,
            299653,
            60,
            299654,
            59,
            299655,
            59,
            299656,
            58,
            299657,
            57,
            299666,
            55,
            299670,
            54,
            299672,
            58,
            299674,
            55,
            299685,
            52,
            299687,
            51,
            299689,
            57,
            299693,
            52,
            299702,
            54,
            299703,
            51,
            299704,
            56,
            299705,
            56,
            299706,
            53,
            299709,
            50,
            299710,
            53,
            299711,
            50,
            299904,
            61,
            299906,
            61,
            299912,
            58,
            299922,
            55,
            299928,
            58,
            299930,
            55,
            301697,
            60,
            301701,
            60,
            301705,
            57,
            301733,
            52,
            301737,
            57,
            301741,
            52,
            301952,
            79,
            301953,
            79,
            301960,
            76,
            301961,
            76,
            316038,
            59,
            316039,
            59,
            316054,
            54,
            316071,
            51,
            316086,
            54,
            316087,
            51,
            316290,
            78,
            316294,
            78,
            316306,
            73,
            316310,
            73,
            318085,
            77,
            318087,
            77,
            318117,
            70,
            318119,
            70,
            318336,
            79,
            318337,
            79,
            318338,
            78,
            318341,
            77,
            318342,
            78,
            318343,
            77,
            430776,
            56,
            430777,
            56,
            430778,
            53,
            430781,
            50,
            430782,
            53,
            430783,
            50,
            431000,
            75,
            431002,
            72,
            431032,
            75,
            431034,
            72,
            432809,
            74,
            432813,
            69,
            432825,
            74,
            432829,
            69,
            433032,
            76,
            433033,
            76,
            433048,
            75,
            433065,
            74,
            433080,
            75,
            433081,
            74,
            447158,
            71,
            447159,
            68,
            447166,
            71,
            447167,
            68,
            447378,
            73,
            447382,
            73,
            447386,
            72,
            447414,
            71,
            447418,
            72,
            447422,
            71,
            449189,
            70,
            449191,
            70,
            449197,
            69,
            449207,
            68,
            449213,
            69,
            449215,
            68,
            449408,
            67,
            449409,
            67,
            449410,
            66,
            449413,
            64,
            449414,
            66,
            449415,
            64,
            449416,
            67,
            449417,
            67,
            449426,
            66,
            449430,
            66,
            449432,
            65,
            449434,
            65,
            449445,
            64,
            449447,
            64,
            449449,
            63,
            449453,
            63,
            449462,
            62,
            449463,
            62,
            449464,
            65,
            449465,
            63,
            449466,
            65,
            449469,
            63,
            449470,
            62,
            449471,
            62,
            449472,
            19,
            449473,
            19,
            449474,
            18,
            449477,
            16,
            449478,
            18,
            449479,
            16,
            449480,
            19,
            449481,
            19,
            449490,
            18,
            449494,
            18,
            449496,
            17,
            449498,
            17,
            449509,
            16,
            449511,
            16,
            449513,
            15,
            449517,
            15,
            449526,
            14,
            449527,
            14,
            449528,
            17,
            449529,
            15,
            449530,
            17,
            449533,
            15,
            449534,
            14,
            449535,
            14,
            449728,
            19,
            449729,
            19,
            449730,
            18,
            449734,
            18,
            449736,
            19,
            449737,
            19,
            449746,
            18,
            449750,
            18,
            449752,
            17,
            449754,
            17,
            449784,
            17,
            449786,
            17,
            451520,
            19,
            451521,
            19,
            451525,
            16,
            451527,
            16,
            451528,
            19,
            451529,
            19,
            451557,
            16,
            451559,
            16,
            451561,
            15,
            451565,
            15,
            451577,
            15,
            451581,
            15,
            451776,
            19,
            451777,
            19,
            451784,
            19,
            451785,
            19,
            465858,
            18,
            465861,
            16,
            465862,
            18,
            465863,
            16,
            465874,
            18,
            465878,
            18,
            465893,
            16,
            465895,
            16,
            465910,
            14,
            465911,
            14,
            465918,
            14,
            465919,
            14,
            466114,
            18,
            466118,
            18,
            466130,
            18,
            466134,
            18,
            467909,
            16,
            467911,
            16,
            467941,
            16,
            467943,
            16,
            468160,
            13,
            468161,
            13,
            468162,
            13,
            468163,
            13,
            468164,
            13,
            468165,
            13,
            468166,
            13,
            468167,
            13,
            580568,
            17,
            580570,
            17,
            580585,
            15,
            580589,
            15,
            580598,
            14,
            580599,
            14,
            580600,
            17,
            580601,
            15,
            580602,
            17,
            580605,
            15,
            580606,
            14,
            580607,
            14,
            580824,
            17,
            580826,
            17,
            580856,
            17,
            580858,
            17,
            582633,
            15,
            582637,
            15,
            582649,
            15,
            582653,
            15,
            582856,
            12,
            582857,
            12,
            582872,
            12,
            582873,
            12,
            582888,
            12,
            582889,
            12,
            582904,
            12,
            582905,
            12,
            596982,
            14,
            596983,
            14,
            596990,
            14,
            596991,
            14,
            597202,
            11,
            597206,
            11,
            597210,
            11,
            597214,
            11,
            597234,
            11,
            597238,
            11,
            597242,
            11,
            597246,
            11,
            599013,
            10,
            599015,
            10,
            599021,
            10,
            599023,
            10,
            599029,
            10,
            599031,
            10,
            599037,
            10,
            599039,
            10,
            599232,
            13,
            599233,
            13,
            599234,
            13,
            599235,
            13,
            599236,
            13,
            599237,
            13,
            599238,
            13,
            599239,
            13,
            599240,
            12,
            599241,
            12,
            599250,
            11,
            599254,
            11,
            599256,
            12,
            599257,
            12,
            599258,
            11,
            599262,
            11,
            599269,
            10,
            599271,
            10,
            599272,
            12,
            599273,
            12,
            599277,
            10,
            599279,
            10,
            599282,
            11,
            599285,
            10,
            599286,
            11,
            599287,
            10,
            599288,
            12,
            599289,
            12,
            599290,
            11,
            599293,
            10,
            599294,
            11,
            599295,
            10,
        ];
        this._p4D = [
            0,
            0,
            1,
            -1,
            0,
            0,
            0,
            1,
            0,
            -1,
            0,
            0,
            1,
            0,
            0,
            -1,
            0,
            0,
            -1,
            1,
            0,
            0,
            0,
            0,
            1,
            -1,
            0,
            0,
            0,
            1,
            0,
            -1,
            0,
            0,
            -1,
            0,
            1,
            0,
            0,
            0,
            -1,
            1,
            0,
            0,
            0,
            0,
            1,
            -1,
            0,
            0,
            -1,
            0,
            0,
            1,
            0,
            0,
            -1,
            0,
            1,
            0,
            0,
            0,
            -1,
            1,
            0,
            2,
            1,
            1,
            0,
            0,
            1,
            1,
            1,
            -1,
            0,
            1,
            1,
            1,
            0,
            -1,
            0,
            2,
            1,
            0,
            1,
            0,
            1,
            1,
            -1,
            1,
            0,
            1,
            1,
            0,
            1,
            -1,
            0,
            2,
            0,
            1,
            1,
            0,
            1,
            -1,
            1,
            1,
            0,
            1,
            0,
            1,
            1,
            -1,
            0,
            2,
            1,
            0,
            0,
            1,
            1,
            1,
            -1,
            0,
            1,
            1,
            1,
            0,
            -1,
            1,
            0,
            2,
            0,
            1,
            0,
            1,
            1,
            -1,
            1,
            0,
            1,
            1,
            0,
            1,
            -1,
            1,
            0,
            2,
            0,
            0,
            1,
            1,
            1,
            -1,
            0,
            1,
            1,
            1,
            0,
            -1,
            1,
            1,
            1,
            4,
            2,
            1,
            1,
            0,
            4,
            1,
            2,
            1,
            0,
            4,
            1,
            1,
            2,
            0,
            1,
            4,
            2,
            1,
            0,
            1,
            4,
            1,
            2,
            0,
            1,
            4,
            1,
            1,
            0,
            2,
            1,
            4,
            2,
            0,
            1,
            1,
            4,
            1,
            0,
            2,
            1,
            4,
            1,
            0,
            1,
            2,
            1,
            4,
            0,
            2,
            1,
            1,
            4,
            0,
            1,
            2,
            1,
            4,
            0,
            1,
            1,
            2,
            1,
            2,
            1,
            1,
            0,
            0,
            3,
            2,
            1,
            0,
            0,
            3,
            1,
            2,
            0,
            0,
            1,
            2,
            1,
            0,
            1,
            0,
            3,
            2,
            0,
            1,
            0,
            3,
            1,
            0,
            2,
            0,
            1,
            2,
            0,
            1,
            1,
            0,
            3,
            0,
            2,
            1,
            0,
            3,
            0,
            1,
            2,
            0,
            1,
            2,
            1,
            0,
            0,
            1,
            3,
            2,
            0,
            0,
            1,
            3,
            1,
            0,
            0,
            2,
            1,
            2,
            0,
            1,
            0,
            1,
            3,
            0,
            2,
            0,
            1,
            3,
            0,
            1,
            0,
            2,
            1,
            2,
            0,
            0,
            1,
            1,
            3,
            0,
            0,
            2,
            1,
            3,
            0,
            0,
            1,
            2,
            2,
            3,
            1,
            1,
            1,
            0,
            2,
            1,
            1,
            1,
            -1,
            2,
            2,
            0,
            0,
            0,
            2,
            3,
            1,
            1,
            0,
            1,
            2,
            1,
            1,
            -1,
            1,
            2,
            2,
            0,
            0,
            0,
            2,
            3,
            1,
            0,
            1,
            1,
            2,
            1,
            -1,
            1,
            1,
            2,
            2,
            0,
            0,
            0,
            2,
            3,
            1,
            1,
            1,
            0,
            2,
            1,
            1,
            1,
            -1,
            2,
            0,
            2,
            0,
            0,
            2,
            3,
            1,
            1,
            0,
            1,
            2,
            1,
            1,
            -1,
            1,
            2,
            0,
            2,
            0,
            0,
            2,
            3,
            0,
            1,
            1,
            1,
            2,
            -1,
            1,
            1,
            1,
            2,
            0,
            2,
            0,
            0,
            2,
            3,
            1,
            1,
            1,
            0,
            2,
            1,
            1,
            1,
            -1,
            2,
            0,
            0,
            2,
            0,
            2,
            3,
            1,
            0,
            1,
            1,
            2,
            1,
            -1,
            1,
            1,
            2,
            0,
            0,
            2,
            0,
            2,
            3,
            0,
            1,
            1,
            1,
            2,
            -1,
            1,
            1,
            1,
            2,
            0,
            0,
            2,
            0,
            2,
            3,
            1,
            1,
            0,
            1,
            2,
            1,
            1,
            -1,
            1,
            2,
            0,
            0,
            0,
            2,
            2,
            3,
            1,
            0,
            1,
            1,
            2,
            1,
            -1,
            1,
            1,
            2,
            0,
            0,
            0,
            2,
            2,
            3,
            0,
            1,
            1,
            1,
            2,
            -1,
            1,
            1,
            1,
            2,
            0,
            0,
            0,
            2,
            2,
            1,
            1,
            1,
            -1,
            0,
            1,
            1,
            1,
            0,
            -1,
            0,
            0,
            0,
            0,
            0,
            2,
            1,
            1,
            -1,
            1,
            0,
            1,
            1,
            0,
            1,
            -1,
            0,
            0,
            0,
            0,
            0,
            2,
            1,
            -1,
            1,
            1,
            0,
            1,
            0,
            1,
            1,
            -1,
            0,
            0,
            0,
            0,
            0,
            2,
            1,
            1,
            -1,
            0,
            1,
            1,
            1,
            0,
            -1,
            1,
            0,
            0,
            0,
            0,
            0,
            2,
            1,
            -1,
            1,
            0,
            1,
            1,
            0,
            1,
            -1,
            1,
            0,
            0,
            0,
            0,
            0,
            2,
            1,
            -1,
            0,
            1,
            1,
            1,
            0,
            -1,
            1,
            1,
            0,
            0,
            0,
            0,
            0,
            2,
            1,
            1,
            1,
            -1,
            0,
            1,
            1,
            1,
            0,
            -1,
            2,
            2,
            0,
            0,
            0,
            2,
            1,
            1,
            -1,
            1,
            0,
            1,
            1,
            0,
            1,
            -1,
            2,
            2,
            0,
            0,
            0,
            2,
            1,
            1,
            -1,
            0,
            1,
            1,
            1,
            0,
            -1,
            1,
            2,
            2,
            0,
            0,
            0,
            2,
            1,
            1,
            1,
            -1,
            0,
            1,
            1,
            1,
            0,
            -1,
            2,
            0,
            2,
            0,
            0,
            2,
            1,
            -1,
            1,
            1,
            0,
            1,
            0,
            1,
            1,
            -1,
            2,
            0,
            2,
            0,
            0,
            2,
            1,
            -1,
            1,
            0,
            1,
            1,
            0,
            1,
            -1,
            1,
            2,
            0,
            2,
            0,
            0,
            2,
            1,
            1,
            -1,
            1,
            0,
            1,
            1,
            0,
            1,
            -1,
            2,
            0,
            0,
            2,
            0,
            2,
            1,
            -1,
            1,
            1,
            0,
            1,
            0,
            1,
            1,
            -1,
            2,
            0,
            0,
            2,
            0,
            2,
            1,
            -1,
            0,
            1,
            1,
            1,
            0,
            -1,
            1,
            1,
            2,
            0,
            0,
            2,
            0,
            2,
            1,
            1,
            -1,
            0,
            1,
            1,
            1,
            0,
            -1,
            1,
            2,
            0,
            0,
            0,
            2,
            2,
            1,
            -1,
            1,
            0,
            1,
            1,
            0,
            1,
            -1,
            1,
            2,
            0,
            0,
            0,
            2,
            2,
            1,
            -1,
            0,
            1,
            1,
            1,
            0,
            -1,
            1,
            1,
            2,
            0,
            0,
            0,
            2,
            3,
            1,
            1,
            0,
            0,
            0,
            2,
            2,
            0,
            0,
            0,
            2,
            1,
            1,
            1,
            -1,
            3,
            1,
            0,
            1,
            0,
            0,
            2,
            0,
            2,
            0,
            0,
            2,
            1,
            1,
            1,
            -1,
            3,
            1,
            0,
            0,
            1,
            0,
            2,
            0,
            0,
            2,
            0,
            2,
            1,
            1,
            1,
            -1,
            3,
            1,
            1,
            0,
            0,
            0,
            2,
            2,
            0,
            0,
            0,
            2,
            1,
            1,
            -1,
            1,
            3,
            1,
            0,
            1,
            0,
            0,
            2,
            0,
            2,
            0,
            0,
            2,
            1,
            1,
            -1,
            1,
            3,
            1,
            0,
            0,
            0,
            1,
            2,
            0,
            0,
            0,
            2,
            2,
            1,
            1,
            -1,
            1,
            3,
            1,
            1,
            0,
            0,
            0,
            2,
            2,
            0,
            0,
            0,
            2,
            1,
            -1,
            1,
            1,
            3,
            1,
            0,
            0,
            1,
            0,
            2,
            0,
            0,
            2,
            0,
            2,
            1,
            -1,
            1,
            1,
            3,
            1,
            0,
            0,
            0,
            1,
            2,
            0,
            0,
            0,
            2,
            2,
            1,
            -1,
            1,
            1,
            3,
            1,
            0,
            1,
            0,
            0,
            2,
            0,
            2,
            0,
            0,
            2,
            -1,
            1,
            1,
            1,
            3,
            1,
            0,
            0,
            1,
            0,
            2,
            0,
            0,
            2,
            0,
            2,
            -1,
            1,
            1,
            1,
            3,
            1,
            0,
            0,
            0,
            1,
            2,
            0,
            0,
            0,
            2,
            2,
            -1,
            1,
            1,
            1,
            3,
            3,
            2,
            1,
            0,
            0,
            3,
            1,
            2,
            0,
            0,
            4,
            1,
            1,
            1,
            1,
            3,
            3,
            2,
            0,
            1,
            0,
            3,
            1,
            0,
            2,
            0,
            4,
            1,
            1,
            1,
            1,
            3,
            3,
            0,
            2,
            1,
            0,
            3,
            0,
            1,
            2,
            0,
            4,
            1,
            1,
            1,
            1,
            3,
            3,
            2,
            0,
            0,
            1,
            3,
            1,
            0,
            0,
            2,
            4,
            1,
            1,
            1,
            1,
            3,
            3,
            0,
            2,
            0,
            1,
            3,
            0,
            1,
            0,
            2,
            4,
            1,
            1,
            1,
            1,
            3,
            3,
            0,
            0,
            2,
            1,
            3,
            0,
            0,
            1,
            2,
            4,
            1,
            1,
            1,
            1,
            3,
            3,
            2,
            1,
            0,
            0,
            3,
            1,
            2,
            0,
            0,
            2,
            1,
            1,
            1,
            -1,
            3,
            3,
            2,
            0,
            1,
            0,
            3,
            1,
            0,
            2,
            0,
            2,
            1,
            1,
            1,
            -1,
            3,
            3,
            0,
            2,
            1,
            0,
            3,
            0,
            1,
            2,
            0,
            2,
            1,
            1,
            1,
            -1,
            3,
            3,
            2,
            1,
            0,
            0,
            3,
            1,
            2,
            0,
            0,
            2,
            1,
            1,
            -1,
            1,
            3,
            3,
            2,
            0,
            0,
            1,
            3,
            1,
            0,
            0,
            2,
            2,
            1,
            1,
            -1,
            1,
            3,
            3,
            0,
            2,
            0,
            1,
            3,
            0,
            1,
            0,
            2,
            2,
            1,
            1,
            -1,
            1,
            3,
            3,
            2,
            0,
            1,
            0,
            3,
            1,
            0,
            2,
            0,
            2,
            1,
            -1,
            1,
            1,
            3,
            3,
            2,
            0,
            0,
            1,
            3,
            1,
            0,
            0,
            2,
            2,
            1,
            -1,
            1,
            1,
            3,
            3,
            0,
            0,
            2,
            1,
            3,
            0,
            0,
            1,
            2,
            2,
            1,
            -1,
            1,
            1,
            3,
            3,
            0,
            2,
            1,
            0,
            3,
            0,
            1,
            2,
            0,
            2,
            -1,
            1,
            1,
            1,
            3,
            3,
            0,
            2,
            0,
            1,
            3,
            0,
            1,
            0,
            2,
            2,
            -1,
            1,
            1,
            1,
            3,
            3,
            0,
            0,
            2,
            1,
            3,
            0,
            0,
            1,
            2,
            2,
            -1,
            1,
            1,
            1,
        ];
    }

    /**
     *
     * @param x -
     * @param y -
     * @param z -
     * @param w -
     * @returns the noise value
     */
    noise(x: number, y: number, z: number, w: number): number {
        const { _perm, _perm4D, _lookup, _STRETCH_4D, _SQUISH_4D, _gradients4D, _NORM_4D } = this;

        const stretchOffset = (x + y + z + w) * _STRETCH_4D,
            xs = x + stretchOffset,
            ys = y + stretchOffset,
            zs = z + stretchOffset,
            ws = w + stretchOffset,
            xsb = Math.floor(xs),
            ysb = Math.floor(ys),
            zsb = Math.floor(zs),
            wsb = Math.floor(ws),
            squishOffset = (xsb + ysb + zsb + wsb) * _SQUISH_4D,
            dx0 = x - (xsb + squishOffset),
            dy0 = y - (ysb + squishOffset),
            dz0 = z - (zsb + squishOffset),
            dw0 = w - (wsb + squishOffset),
            xins = xs - xsb,
            yins = ys - ysb,
            zins = zs - zsb,
            wins = ws - wsb,
            inSum = xins + yins + zins + wins,
            hash =
                (zins - wins + 1) |
                ((yins - zins + 1) << 1) |
                ((yins - wins + 1) << 2) |
                ((xins - yins + 1) << 3) |
                ((xins - zins + 1) << 4) |
                ((xins - wins + 1) << 5) |
                (inSum << 6) |
                ((inSum + wins) << 8) |
                ((inSum + zins) << 11) |
                ((inSum + yins) << 14) |
                ((inSum + xins) << 17);

        let value = 0;

        for (let c: Contribution4D | undefined = _lookup[hash]; c !== undefined; c = c.next) {
            const dx = dx0 + c.dx,
                dy = dy0 + c.dy,
                dz = dz0 + c.dz,
                dw = dw0 + c.dw,
                attn = 2 - dx * dx - dy * dy - dz * dz - dw * dw;

            if (attn > 0) {
                const px = xsb + c.xsb,
                    py = ysb + c.ysb,
                    pz = zsb + c.zsb,
                    pw = wsb + c.wsb,
                    indexPartA = _perm[px & 0xff],
                    indexPartB = _perm[(indexPartA + py) & 0xff],
                    indexPartC = _perm[(indexPartB + pz) & 0xff],
                    index = _perm4D[(indexPartC + pw) & 0xff],
                    valuePart =
                        _gradients4D[index] * dx +
                        _gradients4D[index + 1] * dy +
                        _gradients4D[index + 2] * dz +
                        _gradients4D[index + 3] * dw;

                value += attn * attn * attn * attn * valuePart;
            }
        }
        return value * _NORM_4D;
    }

    seed(clientSeed: number): void {
        const { _p4D, _base4D, _lookupPairs4D } = this;

        const contributions: Contribution4D[] = [];
        for (let i = 0; i < _p4D.length; i += 16) {
            const baseSet = _base4D[_p4D[i]];

            let previous: Contribution4D | null = null,
                current: Contribution4D | null = null;

            for (let k = 0; k < baseSet.length; k += 5) {
                current = this._contribution4D(
                    baseSet[k],
                    baseSet[k + 1],
                    baseSet[k + 2],
                    baseSet[k + 3],
                    baseSet[k + 4],
                );

                if (previous === null) {
                    contributions[i / 16] = current;
                } else {
                    previous.next = current;
                }

                previous = current;
            }

            if (current) {
                current.next = this._contribution4D(_p4D[i + 1], _p4D[i + 2], _p4D[i + 3], _p4D[i + 4], _p4D[i + 5]);
                current.next.next = this._contribution4D(
                    _p4D[i + 6],
                    _p4D[i + 7],
                    _p4D[i + 8],
                    _p4D[i + 9],
                    _p4D[i + 10],
                );
                current.next.next.next = this._contribution4D(
                    _p4D[i + 11],
                    _p4D[i + 12],
                    _p4D[i + 13],
                    _p4D[i + 14],
                    _p4D[i + 15],
                );
            }
        }

        this._lookup = [];

        for (let i = 0; i < _lookupPairs4D.length; i += 2) {
            this._lookup[_lookupPairs4D[i]] = contributions[_lookupPairs4D[i + 1]];
        }

        this._perm = new Uint8Array(256);
        this._perm4D = new Uint8Array(256);
        const source = new Uint8Array(256);

        for (let i = 0; i < 256; i++) {
            source[i] = i;
        }

        let seed = new Uint32Array(1);

        seed[0] = clientSeed;
        seed = shuffleSeed(shuffleSeed(shuffleSeed(seed)));

        for (let i = 255; i >= 0; i--) {
            seed = shuffleSeed(seed);

            const r = new Uint32Array(1);

            r[0] = (seed[0] + 31) % (i + 1);

            if (r[0] < 0) {
                r[0] += i + 1;
            }

            this._perm[i] = source[r[0]];
            this._perm4D[i] = this._perm[i] & 0xfc;
            source[r[0]] = source[i];
        }
    }

    /**
     * @param multiplier -
     * @param xsb -
     * @param ysb -
     * @param zsb -
     * @param wsb -
     * @returns the contribution matrix
     */
    private _contribution4D(multiplier: number, xsb: number, ysb: number, zsb: number, wsb: number): Contribution4D {
        const { _SQUISH_4D } = this;

        return {
            dx: -xsb - multiplier * _SQUISH_4D,
            dy: -ysb - multiplier * _SQUISH_4D,
            dz: -zsb - multiplier * _SQUISH_4D,
            dw: -wsb - multiplier * _SQUISH_4D,
            xsb,
            ysb,
            zsb,
            wsb,
        };
    }
}
